home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
vector.lha
/
vector
/
hvector.h
< prev
next >
Wrap
C/C++ Source or Header
|
1991-11-23
|
7KB
|
265 lines
#ifndef _HVECTOR_H
#define _HVECTOR_H
#include "cvector.h"
// This is a template for a homogenous vector class (like a
// Cartesian vector but with a w scaling coordinate).
// The usual operators are supplied.
#define HomogenousVectorDeclare(T) \
class HVec(T) { \
public: \
static errorHandler error; \
static void badvec(int, const char *); \
static errorHandler setErrorHandler(errorHandler); \
\
T &operator[](int i) { return x[i]; } \
T operator()(int i) const { return x[i]; } \
operator T*() { return x; } \
\
HVec(T)() {} \
\
HVec(T)(T xval, T yval, T zval, T wval = 1) { \
x[0] = xval; x[1] = yval; x[2] = zval; x[3] = wval; \
} \
\
HVec(T)(const HVec(T) &v) { \
x[0] = v(0); x[1] = v(1); x[2] = v(2); x[3] = v(3); \
} \
\
T magnitude() const { \
if (x[3] != 0) \
return sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]) / x[3]; \
else { \
(*error)(0, "w=0 in magnitude"); \
return 0; \
} \
} \
\
HVec(T) &normalize(); \
HVec(T) &canonicalize(); \
\
HVec(T) &operator+=(const HVec(T) &v); \
HVec(T) &operator-=(const HVec(T) &v); \
\
HVec(T) &operator*=(T s) { \
x[0] *= s; \
x[1] *= s; \
x[2] *= s; \
return *this; \
} \
\
HVec(T) &operator/=(T s) { \
T recip = 1.0 / s; \
x[0] *= recip; \
x[1] *= recip; \
x[2] *= recip; \
return *this; \
} \
\
/* Dehomogenize a homogenous vector */ \
operator CVec(T)() const; \
\
/* Homogenize a cartesian vector */ \
HVec(T)(const CVec(T) &v) { \
x[0] = v(0); x[1] = v(1); x[2] = v(2); x[3] = 1; \
} \
\
protected: \
T x[4]; \
}; \
\
/* -V */ \
inline HVec(T) operator-(const HVec(T) &v) \
{ \
return HVec(T)(-v(0), -v(1), -v(2), v(3)); \
} \
\
/* s * V */ \
inline HVec(T) operator*(T s, const HVec(T) &v) \
{ \
return HVec(T)(s * v(0), s * v(1), s * v(2), v(3)); \
} \
\
/* V * s */ \
inline HVec(T) operator*(const HVec(T) &v, T s) { \
return s * v; \
} \
\
/* V / s */ \
inline HVec(T) operator/(const HVec(T) &v, T s) \
{ \
T recip = 1.0 / s; \
return HVec(T)(v(0)*recip, v(1)*recip, v(2)*recip, v(3)); \
} \
\
/* V + V */ \
HVec(T) operator+(const HVec(T) &a, const HVec(T) &b); \
\
/* V - V */ \
HVec(T) operator-(const HVec(T) &a, const HVec(T) &b); \
\
/* V cross V */ \
HVec(T) operator^(const HVec(T) &a, const HVec(T) &b); \
\
/* V dot V */ \
inline T operator*(const HVec(T) &a, const HVec(T) &b) \
{ \
return (a(0) * b(0) + a(1) * b(1) + a(2) * b(2)) / \
(a(3) * b(3)); \
} \
\
/* V == V (no fuzz for comparison) */ \
int operator==(const HVec(T) &a, const HVec(T) &b); \
\
/* V != V (no fuzz for comparison) */ \
inline int operator!=(const HVec(T) &a, const HVec(T) &b) { \
return !(a == b); \
} \
\
ostream &operator<<(ostream &o, const HVec(T) &v);
#define HomogenousVectorImplement(T) \
\
errorHandler HVec(T)::error = &HVec(T)::badvec; \
\
void HVec(T)::badvec(int code, const char *msg) { \
cerr << "HVec(T): error " << code << ": " \
<< msg << endl; \
} \
\
errorHandler HVec(T)::setErrorHandler(errorHandler e) { \
errorHandler old = HVec(T)::error; \
HVec(T)::error = e; \
return old; \
} \
\
\
HVec(T) &HVec(T)::normalize() { \
T mag = this->magnitude(); \
\
if (mag != 0.0) { \
mag = 1 / (mag * x[3]); \
x[0] *= mag; \
x[1] *= mag; \
x[2] *= mag; \
x[3] = 1; \
} \
\
return *this; \
} \
\
HVec(T) &HVec(T)::canonicalize() { \
if (x[3] == 0) \
(*error)(1, "w=0 in canonicalize"); \
else if (x[3] != 1) { \
float recip = 1 / x[3]; \
x[0] *= recip; \
x[1] *= recip; \
x[2] *= recip; \
x[3] = 1; \
} \
return *this; \
} \
\
HVec(T) &HVec(T)::operator+=(const HVec(T) &v) { \
if (x[3] != v(3)) { \
HVec(T) tv(v); \
canonicalize(); \
tv.canonicalize(); \
x[0] += tv(0); \
x[1] += tv(1); \
x[2] += tv(2); \
} else { \
x[0] += v(0); \
x[1] += v(1); \
x[2] += v(2); \
} \
return *this; \
} \
\
HVec(T) &HVec(T)::operator-=(const HVec(T) &v) { \
if (x[3] != v(3)) { \
HVec(T) tv(v); \
canonicalize(); \
tv.canonicalize(); \
x[0] -= tv(0); \
x[1] -= tv(1); \
x[2] -= tv(2); \
} else { \
x[0] -= v(0); \
x[1] -= v(1); \
x[2] -= v(2); \
} \
return *this; \
} \
\
HVec(T) operator+(const HVec(T) &a, const HVec(T) &b) \
{ \
if (a(3) != b(3)) { \
HVec(T) ta = a; \
HVec(T) tb = b; \
ta.canonicalize(); \
tb.canonicalize(); \
return HVec(T)(ta(0)+tb(0), ta(1)+tb(1), ta(2)+tb(2)); \
} else \
return HVec(T)(a(0)+b(0), a(1)+b(1), a(2)+b(2), a(3)); \
} \
\
HVec(T) operator-(const HVec(T) &a, const HVec(T) &b) \
{ \
if (a(3) != b(3)) { \
HVec(T) ta = a; \
HVec(T) tb = b; \
ta.canonicalize(); \
tb.canonicalize(); \
return HVec(T)(ta(0)-tb(0), ta(1)-tb(1), ta(2)-tb(2)); \
} else \
return HVec(T)(a(0)-b(0), a(1)-b(1), a(2)-b(2), a(3)); \
} \
\
HVec(T) operator^(const HVec(T) &a, const HVec(T) &b) \
{ \
HVec(T) ta(a); \
HVec(T) tb(b); \
ta.canonicalize(); \
tb.canonicalize(); \
return HVec(T)(ta(1) * tb(2) - ta(2) * tb(1), \
ta(2) * tb(0) - ta(0) * tb(2), \
ta(0) * tb(1) - ta(1) * tb(0)); \
} \
\
int operator==(const HVec(T) &a, const HVec(T) &b) \
{ \
if (a(3) != b(3)) { \
HVec(T) ta(a); \
HVec(T) tb(b); \
ta.canonicalize(); \
tb.canonicalize(); \
return (ta(0) == tb(0)) && \
(ta(1) == tb(1)) && \
(ta(2) == tb(2)); \
} else \
return (a(0) == b(0)) && \
(a(1) == b(1)) && \
(a(2) == b(2)); \
} \
\
HVec(T)::operator CVec(T)() const { \
HVec(T) a(*this); \
a.canonicalize(); \
return CVec(T)(a(0), a(1), a(2)); \
} \
\
ostream &operator<<(ostream &o, const HVec(T) &v) { \
return o << "( " << v(0) << ' ' << v(1) << ' ' \
<< v(2) << ' ' << v(3) << " )"; \
}
HomogenousVectorDeclare(float);
typedef HVec(float) HVector;
#endif /*_HVECTOR_H*/